home *** CD-ROM | disk | FTP | other *** search
- /*
- * MBTNC.C - 12/20/92 - Deal with the tnc.
- */
-
- #include "mb.h"
-
- #ifdef MCH_AMIGA
- extern PORTS *devtnc; /* Set by inittnc() in amiga.c */
- extern char conn_direction;
- char *tcmds[] =
- #else
- static char *tcmds[] =
- #endif
- {
- "cono on\n",
- "cono of\n",
- "m on\n",
- "m of\n"
- };
-
- #ifdef MCH_AMIGA
- extern char tmpstr[];
- extern short debug;
- extern unsigned char vhfstream,hfstream;
- word save_mode;
-
- /* FIX 12
- The KAM does not just say "*** DISCO" if you send a disco command and
- it is already disconnected. No! That would be too easy. It says:
- 'Can't DISCONNECT, A/V Link state is: DISCONNECTED'
- This can tie distnc() up in loop.
- So look for this as well.
- */
- isother(cp)
- char *cp;
- {
- if(search(cp,"Can't DISCO",11))return true;
- return false;
- }
- #endif
-
- isdis(cp)
- char *cp;
- {
- if (search(cp, "*** DISC", 8)) return true;
- return false;
- }
-
- isreq(cp)
- char *cp;
- {
- if (matchn(cp, "*** conn", 8)) return true;
- if (matchn(cp, "*** Conn", 8)) return true;
- return false;
- }
-
- islink(cp)
- char *cp;
- {
- return matchn(cp, "*** LINK", 8);
- }
-
- iscon(cp)
- char *cp;
- {
- return search(cp, "*** CONN", 8);
- }
-
- isretry(cp)
- char *cp;
- {
- if (matchn(cp, "*** Retry count exceeded", 24)) return true;
- if (matchn(cp, "*** retry count exceeded", 24)) return true;
- return false;
- }
- alloff()
- {
- #ifdef MCH_AMIGA
- PORTS *p;
- if(devtnc->dev == p_serial) {
- if(port->mode & ops) {
- p = port;
- ioport(devtnc);
- outstr("ATS0=0\n");
- waitcmd(2);
- ioport(p);
- }
- return;
- }
- #endif
- allcmd(t_coff); /* Turn off connects */
- allcmd(t_moff); /* Turn off monitoring */
- }
-
- allon()
- {
- #ifdef MCH_AMIGA
- PORTS *p;
- if(devtnc->dev == p_serial) {
- if(port->mode & ops) {
- p = port;
- ioport(devtnc);
- outstr("ATS0=2\n");
- waitcmd(2);
- ioport(p);
- }
- return;
- }
- #endif
- allcmd(t_mon); /* Turn on monitoring */
- allcmd(t_con); /* Turn on connects */
- }
-
- login()
- {
- register PORTS *p;
- register char *i;
-
- readmsg();
- readusr();
-
- p = port;
-
- p->lport = cport;
- cport->lport = p;
- p->errors = 0;
- p->msg = NULL;
- p->cmdcnt = 0;
- p->flags clrbit p_opreq;
- p->ec = p->ecuser;
-
- /*
- * Prepare to check if this user can indeed connect.
- */
-
- switch (p->dev)
- {
- case p_console:
- p->mode = local;
- alloff();
- rduser(p->user->call, p->user);
- unbl(p->line, p->user->call, ln_call);
- log('C', 'S', ' ', p->line);
- break;
-
- case p_tnc:
- p->mode = remote;
- tncstate(); /* Pick up the "... connected to ..." line */
- #ifdef MCH_AMIGA
- /* FIX 8 */
- /* Was this a valid connect? If the BBS saw "*** CONN" but the TNC
- is disconnected (both hf and vhf), then it was monitoring someone's
- data and it is not a valid connection, so log a bad one and get
- out. Need to do same thing when connected to a user who is stupid
- enough to send data that looks like a disconnect.
- */
- if(p->mode == discon) {
- /* force the mode to idle ... the user was never there.
- discon means user was there and then disconnected
- */
- p->mode = idle;
- /* type 'E' log is for errors .... prtlog ignores them */
- /* EF is for the false connected message */
- log('E','F',' ',p->line);
- return;
- }
- #endif
- alloff();
- if (p->tmode) trantnc(); else convtnc();
- /*
- * Remove the "; 1 unacked" that pk-232 puts on status line.
- */
- if ((i = strchr(p->line, ';')) isnt NULL) *i = '\0';
- if ((i = strchr(p->line, '*')) isnt NULL) *i = '\0';
- strcpy(p->line, p->line + 28);
-
- logina(false);
- log('C', p->id, ' ', p->line);
- break;
-
- #ifdef MCH_AMIGA
- case p_nulmdm:
- #endif
- case p_serial:
- p->mode = remote;
- p->flags setbit p_trans;
- alloff();
- strcpy(p->line, p->line + 17);
- logina(false);
- log('C', p->id, ' ', p->line);
- break;
-
- default: ;
- }
- }
-
- /*
- * The login checking process.
- */
-
- logina(link)
- short link;
- {
- register char *p, *q;
- register int ssid;
- register short nd;
-
- char bullfile[11];
-
- remnl(port->line);
-
- /*
- * Clear any pending connect request.
- */
-
- port->flags clrbit p_req;
-
- /*
- * Get the users call and ssid.
- */
-
- parse();
- ssid = pcall(tcall, port->fld[0]);
-
- /*
- * Add the call to J list for port, and for connect.
- */
-
- addcall(port->fld[0], cport);
- addcall(port->fld[0], port);
-
- /*
- * Save call of connected gateway, if user linked here.
- */
-
- if (link) strncpy(tmp->scr, port->user->call, ln_call);
-
- /*
- * Get (or make) this users user record.
- */
-
- rduser(tcall, port->user);
-
- /*
- * Update the data in the user record.
- */
-
- port->user->ssid = ssid;
- if (link) port->user->port = 'L'; else port->user->port = port->id;
-
- /*
- * Get path. Count how many digi in path.
- * First, fix digi path in case is a PK-232.
- */
-
- nd = 3;
- while (port->flds > 3)
- {
- strcat(port->fld[2], port->fld[nd]);
- port->flds--;
- nd++;
- }
-
- nd = 0;
-
- if (link) unbl(port->user->path, tmp->scr, ln_call);
- else if (port->flds > 2)
- {
- nd++;
- p = port->user->path;
- for (q = port->fld[2]; *q; q++)
- if (*q isnt ' ') if ((*p++ = *q) is ',') nd++;
- *p = '\0';
- }
- else *port->user->path = '\0';
-
- /*
- * If this user is excluded, exclude him.
- */
-
- if (port->user->options & u_exclude) { port->mode = exclude; return; }
-
- /*
- * At last, decide if this user CAN connect.
- * If sysop or bbs, can always connect.
- */
-
- if (port->user->options & (u_sysop | u_bbs)) {
- #ifdef MCH_AMIGA
- conn_direction = '<';
- user_title(port->user->call);
- #endif
- outstr(vers);
- return;
- }
-
- /*
- * If this turkey has illegal call, kick him right off.
- */
-
- if (port->priv & p_ilcal) if (!iscall(tcall)) { port->mode = exclude; return; }
-
- /*
- * This user isn't a bbs. If port is bbs only, bye bye.
- */
-
- if (port->priv & p_bbs) { port->mode = exclude; return; }
-
- /*
- * If user connected through too many digi, bye bye.
- */
-
- if (nd > port->ndigi) { port->mode = exclude; return; }
-
- /*
- * Well, this user can indeed connect on this port.
- * Send our "I am a machine message"
- */
-
- outstr(vers);
-
- #ifdef MCH_AMIGA
- /* Put the call in the title bar */
- conn_direction = '<';
- user_title(port->user->call);
- #endif
-
- sprintf(bullfile, "BULLETIN.%c",port->id);
- if ((port->fl = fopen(bullfile, "r")) isnt NULL)
- {
- while( fgets(tmp->scr, scrmax, port->fl) isnt NULL)
- {
- if (chkdis()) break;
- prtx(tmp->scr);
- }
- fclose(port->fl);
- }
-
- /*
- * If not an expert user, give login message and
- * tell about unread messages.
- */
-
- if (!(port->user->options & u_expert))
- prtm(motd);
- newmsg();
- }
-
- /*
- * Execute a command to each port:
- * Connects ok, monitor on, etc.
- */
-
- allcmd(index)
- int index;
- {
- register PORTS *p, *was;
- byte ec;
-
- was = port;
- for (p = porthd; p isnt NULL; p = p->next)
- {
- ioport(p);
- if(p->dev is p_tnc)
- {
- p->flags clrbit p_give;
- ec = p->ec;
- p->ec = p->eccmds;
- outstr(tcmds[index]);
- waitcmd(0);
- p->flags setbit p_give;
- p->ec = ec;
- }
- }
- ioport(was);
- }
-
- alltnc(cp)
- char *cp;
- {
- register PORTS *p, *was;
- byte ec;
-
- was = port;
- for (p = porthd; p isnt NULL; p = p->next) switch(p->dev)
- {
- case p_tnc:
- ioport(p);
- ec = p->ec;
- p->ec = p->eccmds;
- p->flags clrbit p_give;
- outstr(cp);
- waitcmd(0);
- p->flags setbit p_give;
- p->ec = ec;
- break;
-
- default: ;
- }
- ioport(was);
- }
-
- /*
- * Execute a command to the current port:
- * Connects ok, monitor on, etc.
- */
-
- onecmd(index)
- int index;
- {
- register byte ec;
-
- if(port->dev is p_tnc)
- {
- ec = port->ec;
- port->ec = port->eccmds;
- port->flags clrbit p_give;
- outstr(tcmds[index]);
- waitcmd(0);
- port->ec = ec;
- port->flags setbit p_give;
- }
- }
-
- onetnc(cp)
- char *cp;
- {
- register byte ec;
-
- if (port->dev is p_tnc)
- {
- ec = port->ec;
- port->ec = port->eccmds;
- port->flags clrbit p_give;
- outstr(cp);
- waitcmd(0);
- port->ec = ec;
- port->flags setbit p_give;
- }
- }
-
- /*
- * Need to distinguish between "disconect in progress", "disconnected",
- * "connected", "connect in progress".
- */
-
- issta(cp)
- char *cp;
- {
- register char *p;
-
- p = cp;
-
- #ifndef MCH_AMIGA
- if (matchn(cp, "cmd:", 4)) p += 4;
- #else
- /* There could be more than one cmd: lurking on the line */
- while (matchn(cp, "cmd:", 4)) strcpy(p,p+4);
- /*PH Check for beginning of line from a KAM
- of the form 'A/V' or 'A/H' */
- if(p[1] == '/') {
- strcpy(p,p+4);
- }
- #endif
-
- if (!matchn(p, "Link sta", 8)) return false;
-
- if (matchn(p + 15, "DISC", 4) and (strlen(p) < 30)) port->mode = discon;
- return true;
- }
-
- /*
- * Put tnc in converse mode.
- */
-
- convtnc()
- {
- register byte ec;
-
- if(port->dev is p_tnc)
- {
- ec = port->ec;
- port->ec = port->eccmds;
- outstr("conv\n");
- port->ec = ec;
- wait(2);
- }
- }
-
-
- trantnc()
- {
- register byte ec;
-
- if(port->dev is p_tnc)
- {
- ec = port->ec;
- port->ec = port->eccmds;
- outstr("trans\n");
- port->flags setbit p_trans;
- port->ec = ec;
- wait(1);
- }
- }
-
- /*
- * Put tnc in command mode.
- */
-
- cmdtnc()
- {
- register byte ec;
-
- if(port->dev is p_tnc)
- {
- ec = port->ec;
- port->ec = port->eccmds;
- port->flags clrbit p_give;
- if (port->flags & p_trans) breakport(); else outchar(ctl_c);
- waitcmd(1);
- port->ec = ec;
- port->flags setbit p_give;
- port->flags clrbit p_trans;
- }
- }
-
- /*
- * Discover the state of the device on the current port.
- */
-
- tncstate()
- {
- register byte ec;
-
- if(port->mode & idle) return;
-
- if(port->dev is p_tnc) {
- ec = port->ec;
- port->ec = port->eccmds;
- cmdtnc();
- port->flags clrbit p_give;
- #ifdef MCH_AMIGA
- /* If this is the amiga version but it doesn't look like a
- KAM then just use the usual code
- */
- if(!hfstream) {
- #endif
- outstr("C\n");
- while(true) {
- getdat();
- if(issta(port->line)) {
- waitcmd(1);
- port->ec = ec;
- port->flags setbit p_give;
- return;
- }
- else {
- cmdtnc();
- port->flags clrbit p_give;
- outstr("C\n");
- }
- }
- #ifdef MCH_AMIGA
- }
- while(true) {
- /* Try to get an HF status report. */
- /* Ask for HF status first. The reason is that if both streams
- are disconnected, then this procedure will leave the TNC on
- the VHF stream during idle periods. So if you use the TAlk
- command to talk to the TNC and just give it a Connect command
- it will by default send it out the VHF port.
- */
- Delay(10L);
- outchar(hfstream);
- outstr("AC\n");
- getdat();
- /* save the port mode before calling issta. If the HF port is
- DISConnected it will force the mode to discon. This must be
- restored to its original value as it was after the getdat
- when the VHF port is tried because otherwise distnc() and
- other routines will think the VHF side is disconnected even
- if it is not, and they will not force a disconnect when one
- is needed.
- Also, saving the mode here immediately AFTER the first getdat
- will preserve the 'forced' state if the SYSOP had used the
- ^F to force the port to disconnect because we call getdat
- again and the second call won't know the ^F has happened.
- */
- save_mode = port->mode;
- if(issta(port->line)) {
- /* It's a valid status line */
- waitcmd(1);
- /* If it returns not disconnected then it's the HF channel */
- if(port->mode != discon) {
- port->ec = ec;
- port->flags setbit p_give;
- return;
- }
- /* The HF channel is not connected so either the VHF port
- is disconnected, in which case return OR it is connected
- or connecting in which case we still return but force the
- TNC onto the VHF channel
- */
- outchar(vhfstream);
- outstr("AC\n");
- /* now restore the port mode again - getdat will only override
- the existing mode if something goes wrong so if the last
- mode was forced, it will remain forced unless, for example,
- it now sees a *** DISC.
- */
- port->mode = save_mode;
- getdat();
- if(issta(port->line)) {
- waitcmd(1);
- port->ec = ec;
- port->flags setbit p_give;
- return;
- }
- }
- /* If can't get a valid status line from either then fire another
- control C at the port and try again
- */
- cmdtnc();
- port->flags clrbit p_give;
- }
- #endif
- }
- }
-
- /*
- * Disconnect tnc.
- */
- #ifdef MCH_AMIGA
- /* This is the last remaining busy-wait routine in cbbs. If it can be
- removed then the settmr and chktmr routines can also be removed from
- funcs.c
- */
- #endif
-
- distnc()
- {
- register int tsave;
- register short done;
- byte ec;
-
- tncstate();
-
- if(port->mode & idle) return;
-
- ec = port->ec;
- port->ec = port->eccmds;
- switch(port->dev) {
- #ifdef MCH_AMIGA
- case p_nulmdm:
- #endif
- case p_serial:
- if(!(port->mode & discon)) outstr("*** DISCONNECTED\n");
- break;
- case p_tnc:
- if (port->mode & discon) break;
- port->flags clrbit p_give;
- outstr("D\n"); /* This does not eat cmd:, thus dtime not used */
- settmr(&port->expire, port->dtime);
- while(true) {
- if(instat()) {
- tsave = port->ctime;
- port->ctime = port->dtime;
- getdat();
- port->ctime = tsave;
- #ifndef MCH_AMIGA
- if(isdis(port->line))
- #else
- /* FIX 12 */
- if(isdis(port->line) || isother(port->line))
- #endif
- {
- waitcmd(1);
- port->ec = ec;
- port->flags setbit p_give;
- return;
- }
- }
-
- if(!chktmr(port->expire)) {
- outstr("D\n");
- #ifndef MCH_AMIGA
- while(!isdis(port->line)) getdat();
- #else
- /* FIX 12 */
- while(!isdis(port->line) && !isother(port->line)) getdat();
- #endif
- waitcmd(1);
- port->ec = ec;
- port->flags setbit p_give;
- return;
- }
- }
- break;
- }
- port->ec = ec;
- port->mode = discon;
- }
-
- /*
- * Send connect string to tnc.
- */
-
- contnc(p)
- char *p;
- {
- register byte ec;
- #ifdef MCH_AMIGA
- register char *q;
- #endif
-
- ec = port->ec;
- port->ec = true;
- switch (port->dev)
- {
- case p_tnc:
- outstr(p);
- port->ec = port->eccmds;
- #ifndef MCH_AMIGA
- /*
- DON'T DO THIS. MFJ (and some other TNCs) which, for proper BBS operation,
- should have BBSMSGS ON and NEWMODE ON, does NOT send a cmd: prompt after
- a Connect command. With any other combination of BBSMSGS and NEWMODE, the
- stupid thing sends cmd: but the one combination that we need to work,
- doesn't!
- So the waitcmd(0) here will not see a cmd: prompt but it will see, AND
- THROW AWAY, the *** CONNECTED message. This means that the loop which
- will try ot find the CONNECTED message will fail.
- */
- waitcmd(0);
- #endif
- break;
-
- case p_serial:
- #ifdef MCH_AMIGA
- outstr(p);
- while(1) {
- getdat();
- q = port->line;
- /* Ignore the error returns from getdat on a serial line. It looks
- for carrier and dies if it isn't there. But we know it can't be
- there yet.
- */
- if(*q == 0)continue;
- if((*q == '\n') || (*q == '\r'))continue;
- if((*q == 'A') && (*(q+1) == 'T'))continue;
- if(matchn(q,"RING",4))continue;
- if(matchn(q,"CONNECT",7))break;
- port->mode = idle;
- printf("PORT IDLE\n");
- return;
- }
- /* The other end, notably the ZyXEL, may not have seen its CONNECT
- message yet ... so we must Delay here before sending the connect
- */
- Delay(250L);
- port->mode = remote;
- #endif
- #ifdef MCH_AMIGA
- case p_nulmdm:
- /* The initial \n will flush any garbage generated in the modem during
- the connect procedure.
- */
- prtx("\n*** CONNECTED to $O\n");
- #else
- prtx("*** CONNECTED to $O\n");
- #endif
- }
- port->ec = ec;
- }
-
- /*
- * Wait for "cmd:" prompt.
- */
-
- #ifndef MCH_AMIGA
- waitcmd(x)
- int x;
- {
- static char *wanted = "cmd:";
- register short i;
- long l;
- int t;
- if (s_flag & s_dv) t = 5; else t = 2;
- if (x) t = x;
- if(port->dev is p_tnc)
- {
- settmr(&l, t);
- for (i = 0; i < 4;)
- {
- if (instat()) if (inchar() is *(wanted + i)) i++; else i = 0;
- if (!chktmr(l))
- {
- if (!(port->eccmds))
- bdos(2,tolower(port->id),0); return;
- }
- }
- if (!(port->eccmds)) bdos(2,port->id,0);
- }
- }
- #endif
-